﻿using System;
using System.Collections.Generic;
using System.Drawing.Printing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CozeDomain.Helpers;
using CozeDomain.IRepositories;
using CozeDomain.IServices;
using CozeDomain.Models;
using CozeDto.AiDtos;
using D.UtilCore.Dtos;
using MailKit.Search;
using Microsoft.OpenApi.Writers;
using MySqlX.XDevAPI;
using Org.BouncyCastle.Utilities;

namespace CozeDomain.Services
{
    public class CozeAiService : ICozeAiService
    {
        private readonly IProjectEntityRepository _projectEntityRepository;
        private readonly IConversationEntityRepository _conversationEntityRepository;
        public CozeAiService(IProjectEntityRepository projectEntityRepository, IConversationEntityRepository conversationEntityRepository)
        {
            _projectEntityRepository = projectEntityRepository;
            _conversationEntityRepository = conversationEntityRepository;
        }

        /// <summary>
        /// 开启新会话
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public async Task<ApiResult<RepCozeCreeateConversation>> StartConversationAsync(ReqStartConversation reqStartConversation)
        {
            // 获取项目信息，这里涉及每次发送消息都要获取，所以可以把项目信息保存在缓存里面，每次从缓存获取
            var project = await _projectEntityRepository.GetModelAsync(m => m.Id == reqStartConversation.ProjectId);
            if (project == null)
            {
                return new ApiResult<RepCozeCreeateConversation>() { Code = StatusCodeEnum.Waring, Msg = "该项目不存在，请重新在应用市场选择" };
            }
            if (!project.Status.Value)
            {
                return new ApiResult<RepCozeCreeateConversation>() { Code = StatusCodeEnum.Waring, Msg = "该项目已被下线，请重新在应用市场选择" };
            }

            var botInfo = await GetBotInfo(project.BotId, project.Token);
            if (botInfo == null && botInfo.code != 0)
            {
                return new ApiResult<RepCozeCreeateConversation>() { Code = StatusCodeEnum.Waring, Msg = $"[{botInfo.code}]{botInfo.msg}" };
            }

            // 创建新的会话
            var res = await CreateSession(new ReqCozeCreeateSession()
            {
                bot_id = project.BotId,
                messages = new List<EnterMessage>()
                {
                    new EnterMessage { content="您好,请问有什么可以帮助您的？", role="assistant", content_type="text", type="answer" }
                },
            }, project.Token);

            if (res == null)
            {
                return new ApiResult<RepCozeCreeateConversation>() { Code = StatusCodeEnum.Waring, Msg = "创建新的会话失败" };
            }
            if (res.code == 0)
            {
                return new ApiResult<RepCozeCreeateConversation>() { Code = StatusCodeEnum.OK, Data = res };
            }
            return new ApiResult<RepCozeCreeateConversation>() { Code = StatusCodeEnum.Error, Msg = res.code.ToString() };
        }

        /// <summary>
        /// 处理消息,非流式
        /// 在非流式会话场景中，调用发起对话接口后，可以先轮询此 API 确认本轮对话已结束（status=completed）
        /// 再调用接口查看对话消息详情查看本轮对话的模型回复。
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public async Task<ApiResult<RepGetDialogueInfo>> ExecMessageAsync(ReqMessage message)
        {
            // 获取项目信息，这里涉及每次发送消息都要获取，所以可以把项目信息保存在缓存里面，每次从缓存获取
            var project = await _projectEntityRepository.GetModelAsync(m => m.Id == message.ProjectId);
            if (project == null)
            {
                return new ApiResult<RepGetDialogueInfo>() { Code = StatusCodeEnum.Waring, Msg = "该项目不存在，请重新在应用市场选择" };
            }
            if (!project.Status.Value)
            {
                return new ApiResult<RepGetDialogueInfo>() { Code = StatusCodeEnum.Waring, Msg = "该项目已被下线，请重新在应用市场选择" };
            }

            // 获取会话信息，如果不存在则保存会话信息到DB
            var exists = await _conversationEntityRepository.ExistsAsync(m => m.UserId == message.UserId && m.ProjectId == message.ProjectId);
            if (!exists)
            {
                var dbRes = await _conversationEntityRepository.AddAsync(new Entities.ConversationEntity()
                {
                    ProjectId = message.ProjectId,
                    UserId = message.UserId,
                    Title = message.Message,
                    ConversationId = message.ConversationId,
                    ChatId = message.ChatId
                });
            }

            // 发起对话
            var repCreateDialogue = await CreateDialogue(project.Token, message.ConversationId, new ReqCreateDialogue()
            {
                bot_id = project.BotId,
                user_id = message.UserId,
                stream = false,
                auto_save_history = true,
                additional_messages = new List<EnterMessage>()
                {
                    new EnterMessage()
                    {
                        content = message.Message,
                        content_type = message.MessageType,
                        role = "user",
                        type ="question"
                    }
                }
            });

            if (repCreateDialogue == null && repCreateDialogue?.code != 0)
            {
                return new ApiResult<RepGetDialogueInfo>() { Code = StatusCodeEnum.Waring, Msg = $"[{repCreateDialogue.code}]{repCreateDialogue.msg}" };
            }
            if (repCreateDialogue.code == 0)
            {
                // 查看消息结果
                var receve = await GetRtrieve(project.Token, message.ConversationId, repCreateDialogue.data.id);
                if (receve?.data?.status == "completed")
                {
                    var res = await GetDialogueInfo(project.Token, message.ConversationId, repCreateDialogue.data.id);
                    return new ApiResult<RepGetDialogueInfo>() { Code = StatusCodeEnum.OK, Data = res };
                }
                return new ApiResult<RepGetDialogueInfo>() { Code = StatusCodeEnum.Error, Msg = receve.msg };
            }

            return new ApiResult<RepGetDialogueInfo>() { Code = StatusCodeEnum.Error, Msg = repCreateDialogue.msg };
        }

        /// <summary>
        /// 获取某个会话的消息列表历史
        /// </summary>
        /// <param name="reqMessageList"></param>
        /// <returns></returns>
        public async Task<ApiResult<RepQueryMessageList>> QueryMessageListAsync(ReqMessageList reqMessageList)
        {
            // 获取项目信息，这里涉及每次发送消息都要获取，所以可以把项目信息保存在缓存里面，每次从缓存获取
            var project = await _projectEntityRepository.GetModelAsync(m => m.Id == reqMessageList.projectId);
            if (project == null)
            {
                return new ApiResult<RepQueryMessageList>() { Code = StatusCodeEnum.Waring, Msg = "该项目不存在，请重新在应用市场选择" };
            }

            var res = await QueryMessageList(new ReqQueryMessageList()
            {
                chat_id = reqMessageList.chatId
            }, reqMessageList.conversationId, project.Token);

            if (res.code == 0)
            {
                return new ApiResult<RepQueryMessageList>() { Code = StatusCodeEnum.OK, Data = res };
            }

            return new ApiResult<RepQueryMessageList>() { Code = StatusCodeEnum.Error, Msg = res.msg };
        }

        #region 智能体
        /// <summary>
        /// 获取智能体
        /// </summary>
        /// <param name="botId"></param>
        /// <param name="token"></param>
        private async Task<RepGetBotInfo> GetBotInfo(string botId, string token)
        {
            var url = $"https://api.coze.cn/v1/bot/get_online_info?bot_id={botId}&";
            return await HttpHelper<RepGetBotInfo>.GetAsync(url, token);
        }
        #endregion

        #region 会话 Conversation 智能体和用户之间的一段问答交互。一个会话包含一条或多条消息，并且能够自动处理截断，以适应模型的上下文内容。
        /// <summary>
        /// 创建会话
        /// </summary>
        /// <param name="reqCozeCreeateSession"></param>
        /// <returns></returns>
        private async Task<RepCozeCreeateConversation> CreateSession(ReqCozeCreeateSession reqCozeCreeateSession, string token)
        {
            var url = $"https://api.coze.cn/v1/conversation/create";
            return await HttpHelper<RepCozeCreeateConversation>.PostAsync(url, reqCozeCreeateSession, token);
        }
        private void GetSession()
        {

        }
        private void CleanSessionContext()
        {

        }
        /// <summary>
        /// 获取会话列表
        /// </summary>
        private async Task<RepQuerySessionList> QuerySessionList(string bot_id, int page_num = 1, int page_size = 50, string sort_order = "ASC", string connector_id = "1024")
        {
            var url = $"https://api.coze.cn/v1/conversations?bot_id={bot_id}&page_num={page_num}&page_size={page_size}&sort_order={sort_order}&connector_id={connector_id}&";
            return await HttpHelper<RepQuerySessionList>.GetAsync(url);
        }
        #endregion

        #region 消息 Message 一条由用户或智能体创建的消息，消息内容可以包括文本、图片或文件。消息以列表的形式储存在对话中。

        /// <summary>
        /// 创建消息
        /// </summary>
        private async Task<RepCreateMessage> CreateMessage(string token, string conversation_id, ReqCreateMessage reqCreateMessage)
        {
            var url = $"https://api.coze.cn/v1/conversation/message/create?conversation_id={conversation_id}";
            return await HttpHelper<RepCreateMessage>.PostAsync(url, reqCreateMessage, token);
        }

        /// <summary>
        /// 获取消息列表
        /// </summary>
        /// <param name="reqQueryMessageList"></param>
        /// <param name="conversation_id"></param>
        private async Task<RepQueryMessageList> QueryMessageList(ReqQueryMessageList reqQueryMessageList, string conversation_id, string token)
        {
            var url = $"https://api.coze.cn/v1/conversation/message/list?conversation_id={conversation_id}";
            return await HttpHelper<RepQueryMessageList>.PostAsync(url, reqQueryMessageList, token);
        }

        private void GetMessageInfo()
        {

        }
        private void UpdateMessage()
        {

        }
        private void DeleteMessage()
        {

        }

        #endregion

        #region 对话 Chat 对智能体的一次调用

        /// <summary>
        /// 发起对话
        /// </summary>
        private async Task<RepCreateDialogue> CreateDialogue(string token, string conversation_id, ReqCreateDialogue reqCreateDialogue)
        {
            var url = $"https://api.coze.cn/v3/chat?conversation_id={conversation_id}";
            return await HttpHelper<RepCreateDialogue>.PostAsync(url, reqCreateDialogue, token);
        }

        /// <summary>
        /// 查看对话详情
        /// created：对话已创建。
        /// in_progress：智能体正在处理中。
        /// completed：智能体已完成处理，本次对话结束。
        /// failed：对话失败。
        /// requires_action：对话中断，需要进一步处理。
        /// canceled：对话已取消。
        /// </summary>
        private async Task<RepGetRtrieve> GetRtrieve(string token, string conversation_id, string chat_id)
        {
            while (true)
            {
                await Task.Delay(1000);
                var url = $"https://api.coze.cn/v3/chat/retrieve?conversation_id={conversation_id}&chat_id={chat_id}";
                var res = await HttpHelper<RepGetRtrieve>.GetAsync(url, token);
                if (res?.data?.status == "completed")
                {
                    return res;
                }
            }
        }

        /// <summary>
        /// 查看对话消息的详情
        /// </summary>
        private async Task<RepGetDialogueInfo> GetDialogueInfo(string token, string conversation_id, string chat_id)
        {
            var url = $"https://api.coze.cn/v3/chat/message/list?conversation_id={conversation_id}&chat_id={chat_id}";
            return await HttpHelper<RepGetDialogueInfo>.GetAsync(url, token);

        }
        private void SubmitToolExecResult()
        {

        }
        private void CancelDialogue()
        {

        }

        #endregion

        #region 工作流
        private void ExecWorkFlow()
        {

        }
        private void ExecWorkFlowStream()
        {

        }
        private void RecoverWorkFlow()
        {

        }
        private void GetWorkFlowResult()
        {

        }
        private void ExecDialogueStream()
        {

        }

        #endregion
    }
}
